package newtest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.net.ssl.SSLContext;
import java.io.*;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 上报任务流程 版本库：httpclient-4.4.1.jar fastjson-1.2.31.jar
 * 
 * @author zgh
 *
 */
public class InsurerTask {

	static String httpProtocol = "http";
	static String username = "hd@123.com";//保险公司账号
	static String password = "45ffa8fa8f6e67b89b8804b9dc05be07";
	static String ip = "127.0.0.1";
	static int port = 3074;
	static HttpHost target = null;

	public static void main(String[] args) throws Exception {
		/*List<Task> tasks = getTasks("D:\\保险公司.xlsx");
		while (true) {
			for (Task task : tasks) {
				Random random = new Random();
				task.setBusinessNo("" + random.nextInt(100000) + random.nextInt(100000) + random.nextInt(100000)
						+ random.nextInt(100000) + random.nextInt(100000));
				UploadTask(task);
			}
		}*/
		UploadTask(CreateTask("C:\\Users\\gaolq\\Downloads\\3895-0-1-1-video.wmv"));
		// UpdateTastStatus("\"2c8c22a1d811200530e060ef1a7a23de\"", "423");
	}
	
	private static Task CreateTask(String fileName) throws Exception {
		File file = new File(fileName);
		if (!file.exists())
			throw new Exception("文件不存在");
		Task task = new Task();
		task.setTaskSource(2);
		task.setCounterid("123456");
		task.setCounterName("营销员1");
		task.setCounterPhone("13211233222");
		task.setBankCode("20180206");
		task.setSubBankCode("2018020601");
		task.setNodeBankCode("122321");
		task.setSubInsurerCode("HDhb1");
		task.setProduct_code("hdjkx11");
		task.setProduct_name("健康险");
		task.setBusinessType("1");
		Random random=new Random();
		task.setBusinessNo(""+random.nextInt(100000)+random.nextInt(100000)+random.nextInt(100000)+random.nextInt(100000)+random.nextInt(100000));
		task.setCustomerName("张三");
		task.setCustomerCardType(111);
		task.setCustomerCardNo("231181199809067788");
		task.setCustomerBirthday("1990-01-02");
		task.setVideoName(file.getName());
		task.setVideoType(file.getName().substring(file.getName().lastIndexOf(".")+1));
		task.setBusinessSerialNo("1234");
		task.setBatchNo("20170911");
		task.setContent_MD5(DigestUtils.md5Hex(new FileInputStream(file)));
		task.setPayment_term(4);
		task.setRecord_time("2017-11-11 13:13:13");
		task.setFile_time(1800);
		task.setFile_length(file.length() / 1024);
		task.setFileLocalPath(fileName);
		task.setTaskType("100");
		task.setInsuranceperiod("2");
		task.setPayment_year(10);
		task.setPremium(500000.00);
		task.setBranchUnitCode("112222");
		return task;
	}

	private static void UploadTask(Task task) throws Exception {
		CloseableHttpClient httpclient = createSSLClientDefault();
		try {
			HttpClientContext localContext = HttpClientContext.create();
			HttpPost httpPost = new HttpPost(httpProtocol + "://" + ip + ":" + port + "/insurer_task");
			
			String body = JSON.toJSONString(task);
			httpPost.setHeader("Content-Type", "application/json");
			StringEntity stringEntity = new StringEntity(body, "UTF-8");// 解决中文乱码问题
			stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=utf8"));
			httpPost.setEntity(stringEntity);
			CloseableHttpResponse response = httpclient.execute(target, httpPost, localContext);
			try {
				System.out.println("------------------UpdateTask----------------------");
				StatusLine tLine = response.getStatusLine();
				System.out.println(tLine);
				HttpEntity entity = response.getEntity();
				String data = IOUtils.toString(entity.getContent(), "UTF-8");
				System.out.println(data);
				if (tLine.getStatusCode() == 200) {
					JSONObject taskObject = JSON.parseObject(data);
					String etag = fileUpload(task.getFileLocalPath(), taskObject.getString("bucket"), taskObject.getString("object"));
					// String etag = fileUpload("D:\\partVideo.rar", taskObject.getString("bucket"),
					// taskObject.getString("object"));
					System.out.println("------------------上传完成etag" + etag + "----------------------");
					if (!etag.isEmpty()) {
						UpdateTastStatus(etag, taskObject.getString("task_id"));// 更新任务状态
					}
				}
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
	}

	/**
	 * 获取授权
	 * 
	 * @param bucket
	 * @param objectUrl
	 * @return
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	private static Map<String, String> GetInsurerGetauthor(JSONObject jsonObject)
			throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = createSSLClientDefault();
		try {
			HttpClientContext localContext = HttpClientContext.create();
			HttpPut httpPut = new HttpPut(httpProtocol + "://" + ip + ":" + port + "/insurer_getauthor");

			String body = jsonObject.toJSONString();
			httpPut.setHeader("Content-Type", "application/json");
			StringEntity stringEntity = new StringEntity(body, "UTF-8");// 解决中文乱码问题
			stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=utf8"));
			httpPut.setEntity(stringEntity);
			CloseableHttpResponse response = httpclient.execute(target, httpPut, localContext);
			try {
				System.out.println("------------------GetInsurerGetauthor----------------------");
				StatusLine tLine = response.getStatusLine();
				System.out.println(tLine);
				HttpEntity entity = response.getEntity();
				String data = IOUtils.toString(entity.getContent(), "UTF-8");
				System.out.println(data);
				if (tLine.getStatusCode() == 200) {
					JSONObject tmpObject = JSON.parseObject(data);
					Map<String, String> tmpMap = new HashMap<String, String>();
					tmpMap.put("url", tmpObject.getString("url"));
					tmpMap.put("method", tmpObject.getString("method"));
					tmpMap.put("host", tmpObject.getString("host"));
					return tmpMap;
				}
				return null;
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
	}

	/**
	 * 上传视频
	 * 
	 * @param url
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String UploadVideo(Map<String, String> tmpMap, File file)
			throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = createSSLClientDefault();
		HttpPut httpPut = new HttpPut(tmpMap.get("url"));
		httpPut.setHeader("Host", tmpMap.get("host"));
		FileInputStream fInputStream = new FileInputStream(file);
		InputStreamEntity inputStreamEntity = new InputStreamEntity(fInputStream);
		httpPut.setEntity(inputStreamEntity);
		CloseableHttpResponse response = httpclient.execute(httpPut);
		try {
			System.out.println("-------------------UploadVideo---------------------");
			StatusLine tLine = response.getStatusLine();
			System.out.println(tLine);
			System.out.println(response.getFirstHeader("ETag").getValue());
			if (tLine.getStatusCode() == 200) {
				String etag = response.getFirstHeader("ETag").getValue();
				return etag;
			} else {
				return "";
			}
		} finally {
			response.close();
		}
	}

	static CloseableHttpClient httpSSlClient = null;

	/**
	 * 获取受信任httpClient
	 * 
	 * @return
	 */
	public static CloseableHttpClient createSSLClientDefault() {
		if (target == null)
			target = new HttpHost(ip, port, httpProtocol);
		if (httpSSlClient != null)
			return httpSSlClient;
		CredentialsProvider credsProvider = new BasicCredentialsProvider();
		credsProvider.setCredentials(new AuthScope(target.getHostName(), target.getPort()),
				new UsernamePasswordCredentials(username, GetMD5.GetMD5Code(password)));
		SSLContext sslContext;

		try {
			sslContext = new SSLContextBuilder().loadTrustMaterial(null, (certificate, authType) -> true).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[] { "TLSv1.2" },
					null, new NoopHostnameVerifier());
			httpSSlClient = HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultCredentialsProvider(credsProvider)
					.build();
			return httpSSlClient;
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 更新任务状态
	 * 
	 * @param etag
	 * @param taskId
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static boolean UpdateTastStatus(String etag, String taskId) throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = createSSLClientDefault();
		try {
			String enUrl = httpProtocol + "://" + ip + ":" + port + "/insurer_update_task?task_id=" + taskId + "&ETag="
					+ URLEncoder.encode(etag, "UTF-8");
			HttpPost httpPost = new HttpPost(enUrl);

			CloseableHttpResponse response = httpclient.execute(target, httpPost);
			try {
				System.out.println("-------------------UpdateTastStatus---------------------");
				StatusLine tLine = response.getStatusLine();
				System.out.println(tLine);
				HttpEntity entity = response.getEntity();
				String data = IOUtils.toString(entity.getContent(), "UTF-8");
				System.out.println(data);
				if (tLine.getStatusCode() == 200)
					return true;
				else {
					return false;
				}
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}
	}

	/**
	 * 文件上传
	 * 
	 * @param fileName
	 *            文件名
	 * @param bucket
	 *            桶名称
	 * @param object
	 *            对象名称
	 * @return etag
	 * @throws Exception
	 */
	private static String fileUpload(String fileName, String bucket, String object) throws Exception {
		File tmpFile = new File(fileName);
		FileInputStream tmpStream = new FileInputStream(tmpFile);
		long fileLength = tmpFile.length();
		String uploadId = "";
		int fileSize =5 * 1024 * 1024;
		if (fileLength > fileSize) {// 分段上传
			JSONObject taskObject = new JSONObject();
			taskObject.put("bucket", bucket);
			taskObject.put("object", object);
			taskObject.put("method", "POST");
			taskObject.put("subresource", "uploads");
			Map<String, String> tmpMap = GetInsurerGetauthor(taskObject);// 获取分段上传初始化授权
			uploadId = InitPartUploade(tmpMap);
			long tmpValue = fileLength % fileSize;
			if (tmpValue != 0)
				tmpValue = fileLength / fileSize + 1;
			else {
				tmpValue = fileLength / fileSize;
			}
			Map<Integer, String> fileTags = new HashMap<Integer, String>();
			for (int i = 1; i <= tmpValue; i++) {
				try {
					fileSize = (int) Math.min(fileSize, (fileLength - fileSize * (i - 1)));
					taskObject = new JSONObject();
					taskObject.put("bucket", bucket);
					taskObject.put("object", object);
					taskObject.put("method", "PUT");
					JSONObject subObject = new JSONObject();
					subObject.put("uploadId", uploadId);
					subObject.put("partNumber", i);
					taskObject.put("parameters", subObject);
					tmpMap = GetInsurerGetauthor(taskObject);// 获取分段上传授权
					byte[] tmpBytes = new byte[fileSize];
					tmpStream.read(tmpBytes);
					String etag = PartUpload(tmpMap, tmpBytes);
					if (etag.isEmpty())
						return "上传终止";
					fileTags.put(i, etag);
				} catch (Exception ex) {
					System.out.println(ex.getMessage());
				}
			}
			tmpStream.close();

			taskObject = new JSONObject();
			taskObject.put("bucket", bucket);
			taskObject.put("object", object);
			taskObject.put("method", "POST");
			JSONObject subObject = new JSONObject();
			subObject.put("uploadId", uploadId);
			taskObject.put("parameters", subObject);
			// 上传完成
			tmpMap = GetInsurerGetauthor(taskObject);// 获取合并分段授权
			return CompleteUpload(tmpMap, fileTags);
		} else {// 单个上传
			JSONObject taskObject = new JSONObject();
			taskObject.put("bucket", bucket);
			taskObject.put("object", object);
			taskObject.put("method", "PUT");
			Map<String, String> tmpMap = GetInsurerGetauthor(taskObject);// 获取授权
			return UploadVideo(tmpMap, tmpFile);
		}
	}

	public static byte[] getBytes(String filePath) {
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer;
	}

	/**
	 * 分段上传初始化
	 * 
	 * @param tmpMap
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String InitPartUploade(Map<String, String> tmpMap) throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = createSSLClientDefault();
		HttpPost httpPost = new HttpPost(tmpMap.get("url"));
		httpPost.setHeader("Host", tmpMap.get("host"));
		CloseableHttpResponse response = httpclient.execute(httpPost);
		try {
			System.out.println("-------------------InitPartUploade---------------------");
			StatusLine tLine = response.getStatusLine();
			System.out.println(tLine);
			if (tLine.getStatusCode() == 200) {
				HttpEntity entity = response.getEntity();
				String data = IOUtils.toString(entity.getContent(), "UTF-8");
				Document document;
				try {
					document = DocumentHelper.parseText(data);
				} catch (DocumentException e) {
					return "";
				}
				Element element = document.getRootElement();
				if (element != null) {
					Element eUploadId = element.element("UploadId");
					String uploadId = eUploadId.getStringValue();
					return uploadId;
				}
				return "";
			} else {
				return "";
			}
		} finally {
			response.close();
		}
	}

	static CloseableHttpClient httpclientUpload = null;

	/**
	 * 分段上传视频
	 * 
	 * @param tmpMap
	 * @param tmpBytes
	 *            输入字节
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String PartUpload(Map<String, String> tmpMap, byte[] tmpBytes)
			throws ClientProtocolException, IOException {
		try {
			InputStreamEntity inputStreamEntity = new InputStreamEntity(new ByteArrayInputStream(tmpBytes));
			httpclientUpload = createSSLClientDefault();
			HttpPut httpPut = new HttpPut(tmpMap.get("url"));
			httpPut.setHeader("Host", tmpMap.get("host"));
			httpPut.setEntity(inputStreamEntity);
			CloseableHttpResponse response = httpclientUpload.execute(httpPut);
			System.out.println("-------------------PartUpload---------------------");
			StatusLine tLine = response.getStatusLine();
			System.out.println(tLine);
			System.out.println(response.getFirstHeader("ETag").getValue());
			if (tLine.getStatusCode() == 200) {
				String etag = response.getFirstHeader("ETag").getValue();
				return etag;
			} else {
				return "";
			}
		} catch (Exception e) {
			return PartUpload(tmpMap, tmpBytes);
		}
	}

	String testMethod(CloseableHttpClient httpclient) throws IOException {
		try {
			Thread.sleep(1000);
			httpclient.close();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("call testMethod method.");
		return "test";
	}

	/**
	 * 完成分段上传视频
	 * 
	 * @param tmpMap
	 * @param fileTags
	 *            上传的分片集合
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private static String CompleteUpload(Map<String, String> tmpMap, Map<Integer, String> fileTags)
			throws ClientProtocolException, IOException {
		CloseableHttpClient httpclient = createSSLClientDefault();
		HttpPost httpPost = new HttpPost(tmpMap.get("url"));
		httpPost.setHeader("Host", tmpMap.get("host"));

		Document document = DocumentHelper.createDocument();
		Element root = DocumentHelper.createElement("CompleteMultipartUpload");
		document.setRootElement(root);
		for (int i = 1; i <= fileTags.size(); i++) {
			Element partElement = root.addElement("Part");
			Element partNumElement = partElement.addElement("PartNumber");
			partNumElement.addText(String.valueOf(i));
			Element etagElement = partElement.addElement("ETag");
			etagElement.addText(fileTags.get(i));
		}
		StringEntity sEntity = new StringEntity(document.asXML());
		httpPost.setEntity(sEntity);

		CloseableHttpResponse response = httpclient.execute(httpPost);
		try {
			System.out.println("-------------------CompleteUpload---------------------");
			StatusLine tLine = response.getStatusLine();
			System.out.println("-------------------" + tLine.toString() + "---------------------");
			if (tLine.getStatusCode() == 200) {
				String data = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
				try {
					document = DocumentHelper.parseText(data);
				} catch (DocumentException e) {
					return "";
				}
				Element element = document.getRootElement();
				if (element != null) {
					Element etagEle = element.element("ETag");
					String etag = etagEle.getStringValue();
					return etag;
				}
				return "";
			} else {
				return "";
			}
		} finally {
			response.close();
		}
	}
	private static Workbook workBook = null;
	private static List<Task> getTasks(String fileName) throws IOException {
		List<Task> tasks = new ArrayList();
		File file = new File(fileName);
		FileInputStream iStream = new FileInputStream(file);
		Sheet sheet = null;
		try {
			workBook = WorkbookFactory.create(iStream);
		} catch (Exception e) {
			System.out.println("Excel无法解析！");
		}
		int sheetNum = workBook.getNumberOfSheets();
		Task task = null;
		for (int i = 0; i < sheetNum; i++) {
			sheet = workBook.getSheetAt(i);
			task = new Task();
			task.setTaskSource(Integer.parseInt(sheet.getRow(1).getCell(2).getStringCellValue()));
			task.setCounterid(sheet.getRow(2).getCell(2).getStringCellValue());
			task.setCounterName(sheet.getRow(3).getCell(2).getStringCellValue());
			task.setCounterPhone(sheet.getRow(4).getCell(2).getStringCellValue());
			task.setBankCode(sheet.getRow(5).getCell(2).getStringCellValue());
			task.setSubBankCode(sheet.getRow(6).getCell(2).getStringCellValue());
			task.setNodeBankCode(sheet.getRow(7).getCell(2).getStringCellValue());
			task.setSubInsurerCode(sheet.getRow(8).getCell(2).getStringCellValue());
			task.setProduct_name(sheet.getRow(9).getCell(2).getStringCellValue());
			task.setProduct_code(sheet.getRow(10).getCell(2).getStringCellValue());
			task.setBusinessType(sheet.getRow(11).getCell(2).getStringCellValue());
			task.setBusinessNo(sheet.getRow(12).getCell(2).getStringCellValue());
			task.setCustomerName(sheet.getRow(13).getCell(2).getStringCellValue());
			task.setCustomerCardType(Integer.parseInt(sheet.getRow(14).getCell(2).getStringCellValue()));
			task.setCustomerCardNo(sheet.getRow(15).getCell(2).getStringCellValue());
			task.setCustomerBirthday(sheet.getRow(16).getCell(2).getStringCellValue());
			String videoFilePath = sheet.getRow(27).getCell(2).getStringCellValue();
			task.setFileLocalPath(videoFilePath);
			File videoFile = new File(videoFilePath);
			task.setVideoName(videoFile.getName());
			task.setVideoType(videoFile.getName().substring(videoFile.getName().lastIndexOf(".") + 1));
			task.setBusinessSerialNo(sheet.getRow(19).getCell(2).getStringCellValue());
			task.setBatchNo(sheet.getRow(20).getCell(2).getStringCellValue());
			task.setContent_MD5(DigestUtils.md5Hex(new FileInputStream(videoFile)));
			task.setPayment_term(Integer.parseInt(sheet.getRow(22).getCell(2).getStringCellValue()));
			task.setRecord_time(sheet.getRow(23).getCell(2).getStringCellValue());
			task.setFile_time(Integer.parseInt(sheet.getRow(24).getCell(2).getStringCellValue()));
			task.setFile_length(videoFile.length() / 1024);
			tasks.add(task);
		}
		return tasks;
	}
}
